package com.xhkj.testpose

import android.content.ContentValues
import android.content.res.Configuration
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.util.Pair
import android.view.ViewTreeObserver
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.AspectRatio
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.aisway.flashy.utils.mlkit.PoseDetectorProcessor
import com.google.mlkit.vision.pose.defaults.PoseDetectorOptions
import com.xhkj.mylibrary.mlkit.GraphicOverlay
import com.xhkj.mylibrary.mlkit.Urils
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**
 * 检测人脸特征
 */
class PostActivity : AppCompatActivity() {
    private var backgroundExecutor: ExecutorService? = null
    private var imageCapture: ImageCapture? = null
    private var preview: Preview? = null
    private var cameraProvider: ProcessCameraProvider? = null
    private val scope = MainScope()
    private var selectedSize: String? = SIZE_SCREEN

    // Max width (portrait mode)
    private var imageMaxWidth = 0

    // Max height (portrait mode)
    private var imageMaxHeight = 0
    private var isLandScape = false
    private var index = 0
    private var mPreview: PreviewView? = null
    private var overlay: GraphicOverlay? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post)

        val rootView = findViewById<ConstraintLayout>(R.id.root)
        mPreview = findViewById(R.id.preview_view)
        overlay = findViewById(R.id.graphic_overlay)
        findViewById<Button>(R.id.startCamera).setOnClickListener {
            takePhoto()
        }

        rootView.viewTreeObserver.addOnGlobalLayoutListener(
            object : ViewTreeObserver.OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    rootView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                    imageMaxWidth = rootView.width
                    imageMaxHeight = rootView.height
                    startCamera()
                }
            }
        )
        isLandScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
    }

    private fun startCamera() {
        backgroundExecutor = Executors.newSingleThreadExecutor()
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            preview = Preview.Builder().build().also {
                it.setSurfaceProvider(mPreview?.surfaceProvider)
            }
            imageCapture = ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .setTargetAspectRatio(
                    aspectRatio(imageMaxWidth, imageMaxHeight)
                ).build()

            val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
            try {
                cameraProvider?.unbindAll()
                cameraProvider?.bindToLifecycle(
                    this, cameraSelector, preview, imageCapture
                )?.let {
                    val cameraControl = it.cameraControl
                    cameraControl.setZoomRatio(0.5f)
                    Unit
                }
            } catch (e: Exception) {
                e.printStackTrace()
                Log.e("姿势检测", "startCamera: 此相机绑定失败，说明没有被其他相机调用 ${e.message}")
            }
        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return

        // Create time stamped name and MediaStore entry.
        val name = SimpleDateFormat(FILENAME, Locale.CHINA)
            .format(System.currentTimeMillis())
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, name)
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
            }
        }

        // Create output options object which contains file + metadata
        val outputOptions = ImageCapture.OutputFileOptions
            .Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
            .build()

        //旋转图片 180度
//        imageCapture.targetRotation = Surface.ROTATION_180
        imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageSavedCallback {
                override fun onError(exc: ImageCaptureException) {
                    Log.e("拍照的了", "Photo capture failed: ${exc.message}", exc)
                }

                //拍照成功
                override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                    output.savedUri?.let { resultUri ->
                        //去裁剪
                        val resultM = Urils.getBitmapFromContentUri(contentResolver, resultUri)
                        startCheck(resultM)
                    }
                }
            }
        )
    }

    private fun startCheck(imageBitmap: Bitmap) {
        /*val path = CoreUtil.getPath(this@PostActivity, CoreUtil.getFileName())
        CoreUtil.saveBitmapFile(imageBitmap, File(path))
        imageBitmap.recycle()
        Log.i("保存的路径--- ", path)
        overlay?.clear()*/

        val poseDetectorOptions =
            PoseDetectorOptions.Builder().setDetectorMode(PoseDetectorOptions.SINGLE_IMAGE_MODE)
                .build()
        val imageProcessor =
            PoseDetectorProcessor(this, poseDetectorOptions, false, false, false, false, false)

        overlay?.setImageSourceInfo(
            imageBitmap.width, imageBitmap.height, false
        )
        imageProcessor.processBitmap(imageBitmap, overlay!!)
    }

    private val targetedWidthHeight: Pair<Int, Int>
        get() {
            val targetWidth: Int
            val targetHeight: Int
            when (selectedSize) {
                SIZE_SCREEN -> {
                    targetWidth = imageMaxWidth
                    targetHeight = imageMaxHeight
                }

                SIZE_640_480 -> {
                    targetWidth = if (isLandScape) 640 else 480
                    targetHeight = if (isLandScape) 480 else 640
                }

                SIZE_1024_768 -> {
                    targetWidth = if (isLandScape) 1024 else 768
                    targetHeight = if (isLandScape) 768 else 1024
                }

                else -> throw IllegalStateException("Unknown size")
            }
            return Pair(targetWidth, targetHeight)
        }

    override fun onResume() {
        super.onResume()
        backgroundExecutor?.execute {}
    }

    override fun onPause() {
        super.onPause()
        // 停止相机预览
        preview?.setSurfaceProvider(null)

        // 关闭相机
        cameraProvider?.unbindAll()
    }

    override fun onDestroy() {
        super.onDestroy()
        backgroundExecutor?.shutdown()
        backgroundExecutor?.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
        scope.cancel()
    }

    fun aspectRatio(width: Int, height: Int): Int {
        val RATIO_4_3_VALUE = 4.0 / 3.0
        val RATIO_16_9_VALUE = 16.0 / 9.0
        val previewRatio = max(width, height).toDouble() / min(width, height)
        if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {
            return AspectRatio.RATIO_4_3
        }
        return AspectRatio.RATIO_16_9
    }

    companion object {

        private const val SIZE_SCREEN = "w:screen" // Match screen width
        private const val SIZE_1024_768 = "w:1024" // ~1024*768 in a normal ratio
        private const val SIZE_640_480 = "w:640" // ~640*480 in a normal ratio
        private const val SIZE_ORIGINAL = "w:original" // Original image size
        private const val FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS"
    }
}